package com.cltech.log;

import com.cltech.entity.sys.SysOperationLog;
import com.cltech.frame.utils.JWTUtil;
import com.cltech.service.sys.SysOperationLogService;
import com.cltech.util.JsonMapper;
import com.cltech.utils.IPUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author:
 * @description:
 * @create:2019-03-18 14:06
 */
@Aspect
public class LogOperationAspect {

    /**
     * 日志服务.
     */
    private Logger LOGGER = LoggerFactory.getLogger(getClass());
    /**
     * 操作日志.
     */
    @Autowired
    private SysOperationLogService sysOperationLogService;
    /**
     * 定义切入点对象表达式 execution.
     * 注解参数 logOperation
     */
    private static final String POINT_CUT_EXPRESSION = "execution(@com.cltech.log.OperationLogger * *(..)) && @annotation(OperationLogger)";

    /**
     * 切入点声明.
     *
     * @param operationLogger 注解参数提取action Name
     */
    @Pointcut(POINT_CUT_EXPRESSION)
    public void handlePointCut(final OperationLogger operationLogger) {
    }

    /**
     * Before 增强,对handlePointCut进行before增强.
     *
     * @param joinPoint       被通知的对象的对象、参数
     * @param operationLogger 注解参数提取action Name
     */
    @Before(value = "handlePointCut(operationLogger)")
    public void handleBefore(final JoinPoint joinPoint, final OperationLogger operationLogger) {
        try {
            final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            if (request != null) {
                SysOperationLog sysOperationLog = new SysOperationLog();
                String authorization = request.getHeader("Authorization");
                String userId = JWTUtil.getUserId(authorization);
                sysOperationLog.setOperator(userId);
                sysOperationLog.setAction(operationLogger.action());
                sysOperationLog.setIp(IPUtil.getRemoteAddress(request));
                final String servletPath = request.getServletPath();
                sysOperationLog.setContent(String.format("%s|%s", servletPath != null ? servletPath : "",
                        JsonMapper.buildNormalMapper().toJson(request.getParameterMap())));
                sysOperationLog.setPoint(joinPoint.getStaticPart().toString());
                sysOperationLog.setCreateTime(new Date());
                sysOperationLogService.asyncSave(sysOperationLog);
            }
        } catch (final Exception e) {
            LOGGER.error("OperationLoggerAspect before...", e);
        }
    }
}
